import 'dart:convert';

import 'package:floor/floor.dart';
import 'package:get/get.dart';
import 'package:intl/intl.dart';
import 'package:share_fit/app/controllers/home/exercise_records/model/exercise_type.dart';
import 'package:share_fit/app/helper/ext/tr_ext.dart';
import 'package:share_fit/app/models/base_model.dart';
import 'package:share_fit/app/models/sports/sports_model.dart';
import 'package:share_fit/app/tools/date_tool.dart';
import 'package:share_fit/app/tools/unit_util.dart';
import 'package:share_fit/generated/locales.g.dart';

@Entity(tableName: 'workout', indices: [
  Index(value: ['calendar', 'address'])
])
class WorkoutModel extends BaseModel {
  /// 开始时间，格式 ：yyyyMMddHHmmss
  @ColumnInfo(name: 'start_time')
  String? startTime;

  /// 结束时间，格式 ：yyyyMMddHHmmss
  @ColumnInfo(name: 'end_time')
  late String? endTime;

  /// 日期 ，格式 ：yyyyMMdd
  late String calendar;
  late int? step;

  /// 距离，单位：米
  late int? distance;
  late double? calories;
  late int? heart;

  /// 最大心率值，单位：BMP
  @ColumnInfo(name: 'max_heart')
  late int? maxHeart;

  /// 最小心率值，单位：BMP
  @ColumnInfo(name: 'min_heart')
  late int? minHeart;

  /// 次数 （跳绳次数、游泳划水次数、划船划桨次数）
  late int? count;

  /// 运动时长，单位：秒
  late int? duration;

  /// 运动类型，具体见 WorkoutType
  @ColumnInfo(name: 'sports_type')
  late int? sportsType;

  /// 配速，单位：秒/公里
  late int? pace;

  /// 平均速度，单位：分米/秒
  @ColumnInfo(name: 'ver_speed')
  late int? verSpeed;

  /// 频率（步频、游泳划水频率、划船频率）
  late int? frequency;

  /// 步幅，单位：厘米
  late int? stride;

  /// 跳绳最大连跳数
  @ColumnInfo(name: 'longest_streak')
  late int? longestStreak;

  /// 跳绳绊绳次数(中断次数)
  late int? tripped;

  /// 跳绳跳速 ，单位：次/分钟
  @ColumnInfo(name: 'jump_rope_frequency')
  late int? jumpRopeFrequency;

  /// 泳姿 ，1: 蛙泳 2: 自由泳 3: 蝶泳 4: 仰泳 5: 混合泳
  @ColumnInfo(name: 'swim_type')
  late int? swimType;
  @ColumnInfo(name: 'swim_pool_length')
  late int? swimPoolLength;
  @ColumnInfo(name: 'trip_times')
  late int? tripTimes;
  @ColumnInfo(name: 'swim_average_swolf')
  late int? swimAverageSwolf;

  /// 海拔，单位：分米
  late int? altitude;

  /// 最高海拔，单位：分米
  @ColumnInfo(name: 'highest_altitude')
  late int? highestAltitude;

  /// 最低海拔，单位：分米
  @ColumnInfo(name: 'lowest_altitude')
  late int? lowestAltitude;

  /// 累计爬升高度：单位：分米
  @ColumnInfo(name: 'total_rise_height')
  late int? totalRiseHeight;

  /// 累计下降高度，单位：分米
  @ColumnInfo(name: 'total_drop_height')
  late int? totalDropHeight;

  /// 上楼层数
  @ColumnInfo(name: 'floors_up')
  late int? floorsUp;

  /// 下楼层数
  @ColumnInfo(name: 'floors_down')
  late int? floorsDown;

  /// 拉桨时间 单位 秒
  @ColumnInfo(name: 'pull_time')
  late int? pullTime;

  /// 收桨时间 单位 秒
  @ColumnInfo(name: 'free_time')
  late int? freeTime;

  /// 运动模块产生的运动记录id，标记这条记录是特殊的，在删除操作时需要排除
  @ColumnInfo(name: 'sport_id')
  late int? sportId;

  /// GPS数据列表
  @ColumnInfo(name: 'gps_data')
  String? gpsDataList;

  /// 运动详情数据列表
  @ColumnInfo(name: 'detail_data')
  String? detailDataList;

  WorkoutModel(
      this.startTime,
      this.endTime,
      this.calendar,
      this.step,
      this.distance,
      this.calories,
      this.heart,
      this.maxHeart,
      this.minHeart,
      this.count,
      this.duration,
      this.sportsType,
      this.pace,
      this.verSpeed,
      this.frequency,
      this.stride,
      this.longestStreak,
      this.tripped,
      this.jumpRopeFrequency,
      this.swimType,
      this.swimPoolLength,
      this.tripTimes,
      this.swimAverageSwolf,
      this.altitude,
      this.highestAltitude,
      this.lowestAltitude,
      this.totalRiseHeight,
      this.totalDropHeight,
      this.floorsUp,
      this.floorsDown,
      this.pullTime,
      this.freeTime,
      this.sportId,
      this.gpsDataList,
      this.detailDataList, {
        super.id,
        super.address,
        super.dateCreated,
        super.dateModified,
      });

  WorkoutModel.init({this.startTime = ''});

  void fromSport(SportsModel sm) {
    // sportId = map['recordId'];
    // // status = map['status'];
    // startTime = map['startTime'];
    // endTime = map['endTime'];
    // calories = map['calorie'].toDouble();
    // distance = map['distance'];
    // duration = map['duration'];
    // step = map['step'] ?? 0;
    // pace = map['avgPace'];
    // stride = map['stride'];
    // // totalTime = map['totalTime'];
    // verSpeed = map['speed'];
    // totalRiseHeight = map['climb'];  // ? 疑问
    // heart = map['heartRate']; // 上报的字段中没有，需要从实时上报数据中汇总再平均
    // minHeart = map['hrAbsMinPeak'];
    // maxHeart = map['hrAbsMaxPeak'];
    // // trainingEffect = map['trainingEffect'];
    // oxygenConsumption = map['oxygenConsumption'];
    // oxygenUptake = map['oxygenUptake'];
    // recoveryTime = map['recoveryTime'];
    // workoutType = map['workoutType'];
    // algType = map['algType'];
    // longestStreak = map['longestStreak'];
    // trippedCount = map['trippedCount'];
    // fatConsumption = map['fatConsumption'];
    // fatPercentage = map['fatPercentage'];
    // fatWeight = map['fatWeight'];
    // fitnessAge = map['fitnessAge'];
    // lowestAltitude = map['lowestAltitude'];
    // highestAltitude = map['lowestAltitude'];
    // floorsUp = map['floorsUp'];
    // floorsDown = map['floorsDown'];
    // pullTime = map['pullTime'];
    // freeTime = map['freeTime'];

    address = sm.address;
    sportId = sm.recordId;
    sportsType = sm.workoutType;
    duration = sm.duration ?? 0;
    calories = sm.calorie?.toDouble();
    distance = sm.distance ?? 0;
    step = sm.step;
    pace = (distance == 0) ? 0 : (distance == 0 ? 0 : duration! ~/ distance!);
    heart = sm.heart;
    minHeart = sm.hrAbsMinPeak;
    maxHeart = sm.hrAbsMaxPeak;
    count = 0;
    verSpeed = sm.speed;
    frequency = 0;
    stride = sm.stride;
    longestStreak = 0;
    tripped = 0;
    jumpRopeFrequency = 0;
    swimType = 0;
    swimPoolLength = 0;
    tripTimes = 0;
    swimAverageSwolf = 0;
    altitude = 0;
    highestAltitude = sm.highestAltitude;
    lowestAltitude = sm.lowestAltitude;
    totalRiseHeight = 0;
    totalDropHeight = 0;
    floorsUp = sm.floorsUp;
    floorsDown = sm.floorsDown;
    pullTime = sm.pullTime;
    freeTime = sm.freeTime;

    startTime = DateTool.getyyyyMMddHHmmss(DateTime.fromMillisecondsSinceEpoch(sm.startTime! * 1000));
    endTime = DateTool.getyyyyMMddHHmmss(DateTime.fromMillisecondsSinceEpoch(sm.endTime! * 1000));
    calendar = DateTool.getYMD(sm.startTime!);
  }

  @override
  bool from(Map map) {
    // TODO: implement from
    throw UnimplementedError();
  }

  @override
  List<Object?> get props => [];

  /// 解析运动记录中的gps列表，
  List get gpsList {
    if (gpsDataList != null && gpsDataList!.isNotEmpty) {
      return jsonDecode(gpsDataList!);
    }
    return [];
  }

  /// 解析运动记录中的详细数据列表，
  List get detailList {
    if (detailDataList != null && detailDataList!.isNotEmpty) {
      return jsonDecode(detailDataList!);
    }
    return [];
  }

  bool get isAppSports => sportId != null && sportId! > 0;

  /// 获取运动记录详细数据的唯一标识
  int? get detailDataIdentifierId => (sportId == 0 || sportId == null) ? id : sportId;

  get isEmpty => startTime!.isEmpty;

  /// 获取格式化的时和分文本，例如: 10:02
  get HMText {
    DateTime temp = DateTime.parse('${startTime!.substring(0, 8)}T${startTime!.substring(8)}');
    // return '${DateFormat.MMMMd(Get.locale?.languageCode).format(temp)} ${DateFormat.Hm(Get.locale?.languageCode).format(temp)}';
    return DateFormat.Hm(Get.locale?.languageCode).format(temp);
  }

  /// 获取配速的文本, 返回配速格式化为分秒的信息
  get getPaceText {
    int paceTemp = pace ?? 0;
    if (UnitUtil.getLengthUnit() == 1) {
      paceTemp = paceTemp ~/ 0.62137;
    }

    var ms = '';
    if (paceTemp > 0) {
      int m = paceTemp ~/ 60;
      int s = paceTemp % 60;
      String sec = s < 10 ? '0$s' : '$s';
      ms = "$m'$sec\"";
    }
    return ms.isEmpty ? ms : '${LocaleKeys.exercise_pace_text.ts} $ms';
  }

  double transDistance() {
    int unit = UnitUtil.getLengthUnit();
    if (unit == 0) {
      return distance! / 1000;
    } else if (unit == 1) {
      return (distance! / 1000 * 0.62137);
    } else {
      return 0.0;
    }
  }

  /// 距离格式化，转换为公里数，再拼接上长度的单位
  String distanceFormat() {
    int unit = UnitUtil.getLengthUnit();
    double temp = transDistance();
    if (unit == 0) {
      return temp <= 0 ? '' : '${temp.toStringAsFixed(2)} ${LocaleKeys.length_unit_km.ts}';
    } else if (unit == 1) {
      return temp <= 0 ? '' : '${temp.toStringAsFixed(2)} ${LocaleKeys.length_unit_mi.ts}';
    } else {
     return '';
    }
  }

  /// 卡路里格式化，再拼接上卡路里的单位
  get caloriesFormat {
    return '${calories?.toInt()} ${LocaleKeys.thermal_unit_kcal.ts}';
  }

  /// 获取运动类型名称
  get transformTypeText => Type.i18nNameBy(sportsType!);

  /// 获取时长格式化后的字符串
  get durationText => DateTool.second2HMS(duration!);

  /// 获取运动类型对应的图标
  get sportTypeImg => Type.realImgBy(sportsType!);

  get startTimeFormat {
    return DateTool.toFullYMDHMS(startTime!);
  }
}

class WorkoutSummary {
  int sessions = 0;
  int distance = 0;
  List<WorkoutSummaryItem> summaryList = [];

  WorkoutSummary({this.sessions = 0, this.distance = 0, this.summaryList = const []});

  /// 汇总运动次数
  get totalTimes => summaryList.isEmpty ? 0 : summaryList.map((e) => e.timesSum).reduce((value, element) => value + element);

  /// 汇总距离，计算出公里数
  String totalDistance(int unit) {
    int sum = summaryList.isEmpty ? 0 : summaryList.map((e) => e.distanceSum).reduce((value, element) => value + element);
    if (unit == 0) {
      double temp = (sum / 1000);
      return temp <= 0 ? '--' : '${temp.toStringAsFixed(2)} ${LocaleKeys.length_unit_km.ts}';
    } else if (unit == 1) {
      double temp = (sum / 1000 * 0.62137);
      return temp <= 0 ? '--' : '${temp.toStringAsFixed(2)} ${LocaleKeys.length_unit_mi.ts}';
    } else {
      return '--';
    }
  }

  /// 汇总卡路里
  get totalCalories {
    return summaryList.isEmpty ? 0 : summaryList.map((e) => e.caloriesSum).reduce((value, element) => value + element);
  }
}

class WorkoutSummaryItem {
  String date = '';
  List<WorkoutModel> workouts = [];

  WorkoutSummaryItem(this.date, this.workouts);

  /// 格式化日期，适配国际化
  get getDateText => DateFormat.yMMMd(Get.locale?.languageCode).format(DateTime.parse(date));

  /// 格式化公里数，获得公里数和长度单位的文本
  get distanceFormatText {
    return '${(distanceSum / 1000).toStringAsFixed(2)} ${LocaleKeys.length_unit_km.ts}';
  }

  /// 获取运动次数的文本
  get timesText {
    return '$timesSum${LocaleKeys.exercise_times_text.ts}';
  }

  /// 汇总某个日期下的所有卡路里
  get caloriesSum => workouts.map((e) => e.calories).reduce((value, element) => value! + element!);

  /// 汇总某个日期下的所有距离，单位为米
  get distanceSum => workouts.map((e) => e.distance).reduce((value, element) => value! + element!);

  /// 汇总某个日期下运动次数
  get timesSum => workouts.length;
}
